/* (c) 2012 Jungo Ltd. All Rights Reserved. Jungo Confidential */
#include "includes.h"
#include "tra_hcit.h"
#include "tc_const.h"
#include "app_Mobvoi_includes.h"
#include "app_drc.h"
#include "app_tlv.h"
#include "M510_calibration.h"
//#include "driver_usb.h"
#include "app_bt.h"
#ifdef CONFIG_PRODUCT_TEST_INF
#include "driver_icu.h"
#include "bt_spp.h"
#endif

#if PTS_TESTING
#include "pts/pts.h"
#endif



#if (DEBUG_BASEBAND_MONITORS == 1)
extern void TC_Read_Local_Baseband_Monitors_Via_App(void);
extern void TC_Read_Non_Signal_Test_Monitors(void);
extern void LSLCstat_Reset_Monitors();
#endif
#if (DEBUG_SCATTERNET_MONITORS == 1)
extern void TC_Read_Local_LMPconfig_Monitors_Via_App(void);
#endif

extern void TRAhcit_Rx_Char(uint8_t ch);
extern void juart_receive(uint8_t *buf, uint16_t size);

extern void app_env_dump(void);
extern result_t a2dp_cmd_disconnect(void);
extern result_t hf_cmd_disconnect(void);
extern result_t spp_slc_disconnect(void);
extern void app_print_linkkey(void);
extern uint32_t XVR_analog_reg_save[16];

extern void print_page_scan_status(void);

unsigned char uart_rx_buf[0x100 /*RX_FIFO_THRD*/] = {0};
unsigned char uart_tx_buf[TX_FIFO_THRD] = {0};
volatile BOOL uart_rx_done = FALSE;
volatile unsigned int uart_rx_index = 0;
HCI_COMMAND_PACKET *pHCIrxBuf = (HCI_COMMAND_PACKET *)(&uart_rx_buf[0]);
HCI_EVENT_PACKET *pHCItxBuf = (HCI_EVENT_PACKET *)(&uart_tx_buf[0]);
#ifdef CONFIG_BLUETOOTH_AVDTP_SCMS_T
extern void security_control_cp_support_print(void); // print the array's param for check
#endif

#if A2DP_ROLE_SOURCE_CODE

extern void a2dpSrcConnectRemoteDevice(btaddr_t *remote_btaddr_p);
extern void a2dpSnkConnectRemoteDevice(btaddr_t *remote_btaddr);
extern uint8_t get_a2dp_role(void);

#endif

enum
{
    DBG_HCI_STATE_RX_TYPE,
    DBG_HCI_STATE_RX_COMMAND_OPCODE1,
    DBG_HCI_STATE_RX_COMMAND_OPCODE2,
    DBG_HCI_STATE_RX_COMMAND_LENGTH,
    DBG_HCI_STATE_RX_DATA_START,
    DBG_HCI_STATE_RX_DATA_CONTINUE,
    DBG_HCI_STATE_RX_DATA_COMMIT
};
#if (CONFIG_PRE_EQ == 1 || CONFIG_HFP_SPK_EQ == 1 || CONIFG_HFP_MIC_EQ == 1)
static uint8 sw_eq_flag = 0;
#endif
// uint8_t dbg_hci_rx_buf[255] = {0};
static uint8_t s_dbg_hci_rx_state;
static volatile uint8_t *s_dbg_hci_rx_pdu_buf = (uint8_t *)&uart_rx_buf[4];
static volatile uint16_t s_dbg_hci_rx_pdu_length;
static uint8_t s_dbg_hci_rx_length;
uint8_t *s_dbg_hci_rx_head_buf = (uint8_t *)&uart_rx_buf[0];

void show_bt_stack_status(void);
void app_bt_status_show(void);
#ifdef Mobvoi_DEBUG
void app_bt_debug_show(void);
#endif
/*
 * uart_initialise
 *
 * This function initialises the UART registers & UART driver paramaters.
 */
void uart_initialise(uint32_t baud_rate)
{
    uint32_t baud_divisor = baud_divisor = 26000000 / baud_rate - 1;

    REG_UART0_CONF = (DEF_STOP_BIT << SFT_UART0_CONF_STOP_LEN) | ((DEF_PARITY_MODE & 0x1) << SFT_UART0_CONF_PAR_MODE) | (((DEF_PARITY_EN >> 1) & 0x1) << SFT_UART0_CONF_PAR_EN) | (DEF_DATA_LEN << SFT_UART0_CONF_LEN) | (baud_divisor << SFT_UART0_CONF_CLK_DIVID) | (DEF_RX_EN << SFT_UART0_CONF_RX_ENABLE) | (DEF_TX_EN << SFT_UART0_CONF_TX_ENABLE);
    REG_UART0_FIFO_CONF = ((RX_FIFO_THRD << SFT_UART0_FIFO_CONF_RX_FIFO_THRESHOLD) | (TX_FIFO_THRD << SFT_UART0_FIFO_CONF_TX_FIFO_THRESHOLD));
    REG_UART0_INT_ENABLE = MSK_UART0_INT_ENABLE_RX_STOP_END_MASK | MSK_UART0_INT_ENABLE_RX_FIFO_NEED_READ_MASK;

    REG_GPIO_0x00 = 0x70;
    REG_GPIO_0x01 = 0x7C;
}
void uart1_initialise(uint32_t baud_rate)
{

    uint32_t baud_divisor = baud_divisor = 26000000 / baud_rate - 1;
    // REG_SYSTEM_CPU_INT_EN0
    REG_UART1_CONF = (DEF_STOP_BIT << SFT_UART1_CONF_STOP_LEN) | ((DEF_PARITY_MODE & 0x1) << SFT_UART1_CONF_PAR_MODE) | (((DEF_PARITY_EN >> 1) & 0x1) << SFT_UART1_CONF_PAR_EN) | (DEF_DATA_LEN << SFT_UART1_CONF_LEN) | (baud_divisor << SFT_UART1_CONF_CLK_DIVID) | (DEF_RX_EN << SFT_UART1_CONF_RX_ENABLE) | (DEF_TX_EN << SFT_UART1_CONF_TX_ENABLE);
    REG_UART1_FIFO_CONF = ((RX_FIFO_THRD << SFT_UART1_FIFO_CONF_RX_FIFO_THRESHOLD) | (TX_FIFO_THRD << SFT_UART1_FIFO_CONF_TX_FIFO_THRESHOLD));
    REG_UART1_INT_ENABLE = MSK_UART1_INT_ENABLE_RX_STOP_END_MASK | MSK_UART1_INT_ENABLE_RX_FIFO_NEED_READ_MASK;

    REG_GPIO_0x10 = 0x70;           // output enable GPIO16 2nd Function Enable TX
    REG_GPIO_0x11 = 0x7C;           // input enable  GPIO17 2nd Function Enable  RX
    system_gpio_peri_config(16, 1); // GPIO16,mode 0: Perial Mode 2 function
    system_gpio_peri_config(17, 1); // GPIO17,mode 0: Perial Mode 2 function
}

void uart_gpio_disable(void)
{
    REG_GPIO_0x00 = 0x3c; // input and pull up
    REG_GPIO_0x01 = 0x3c; // input and pull up
}
void uart_gpio_enable(void)
{
    REG_GPIO_0x00 = 0x70; // Tx and pull up;
    REG_GPIO_0x01 = 0x7C; // Rx and pull up;
}

void uart_send(unsigned char *buf, unsigned int len)
{
    while (len)
    {
        if (REG_UART0_FIFO_STATUS & MSK_UART0_FIFO_STATUS_FIFO_WR_READY)
        {
            REG_UART0_FIFO_PORT = *buf++;
            len--;
        }
    }
}

#ifdef CONFIG_USE_USB
void uart1_send(unsigned char *buf, unsigned int len)
{
    while (len)
    {
        if (REG_UART1_FIFO_STATUS & MSK_UART1_FIFO_STATUS_FIFO_WR_READY)
        {
            REG_UART1_FIFO_PORT = *buf++;
            len--;
        }
    }
}
#endif

#define PRINT_BUF_PREPARE(rc, buf, fmt)          \
    int rc;                                      \
    va_list args;                                \
    va_start(args, fmt);                         \
    rc = vsnprintf(buf, sizeof(buf), fmt, args); \
    va_end(args);                                \
    buf[sizeof(buf) - 1] = '\0';
#define PRINT_BUF_SIZE 0X100

int32_t os_printf(const char *fmt, ...)
{
#if (BT_HOST_MODE == JUNGO_HOST)
    char buf[PRINT_BUF_SIZE];

    // unsigned int oldmask = get_spr(SPR_VICMR(0));    //read old spr_vicmr
    // set_spr(SPR_VICMR(0), 0x00);                     //mask all/low priority interrupt.

    PRINT_BUF_PREPARE(rc, buf, fmt);

#if 0// CONFIG_USE_USB
    // #ifdef AUDIO_TX
    //     uart_send((unsigned char *)&buf[0], rc);
    // #else
    //     uart1_send((unsigned char *)&buf[0], rc);
    // #endif
    uart1_send((unsigned char *)&buf[0], rc);
#else
    if (app_bt_flag2_get(APP_FLAG2_VUSB_DLP_PRINTF) && (vusb_get_mode() == VUSB_COMM_MODE))
        vusb_dlp_send((unsigned char *)&buf[0], rc);
    else
        uart_send((unsigned char *)&buf[0], rc);
#endif

    // set_spr(SPR_VICMR(0), oldmask);                  //recover the old spr_vicmr.
    return rc;
#else
    // unsigned int oldmask = get_spr(SPR_VICMR(0));    //read old spr_vicmr
    // set_spr(SPR_VICMR(0), 0x00);                     //mask all/low priority interrupt.
    os_delay_us(10);
    // set_spr(SPR_VICMR(0), oldmask);                  //recover the old spr_vicmr.
    return 0;
#endif
}

int32_t os_null_printf(const char *fmt, ...)
{
    return 0;
}

void clear_uart_buffer(void)
{
    uart_rx_index = 0;
    uart_rx_done = FALSE;
    memset(uart_rx_buf, 0, sizeof(uart_rx_buf)); /**< Clear the RX buffer */
    memset(uart_tx_buf, 0, sizeof(uart_tx_buf)); /**< Clear the TX buffer */
}

void M510_Uart_Tx(void)
{
    unsigned int tx_len = HCI_EVENT_HEAD_LENGTH + pHCItxBuf->total;
    pHCItxBuf->code = TRA_HCIT_EVENT;
    pHCItxBuf->event = HCI_COMMAND_COMPLETE_EVENT;
#if (CONFIG_USE_USB == 0)
    uart_send(uart_tx_buf, tx_len);
#else
    uart_send(uart_tx_buf, tx_len);
#endif
}

static void app_debug_showstack(void)
{
    extern uint32_t _sbss_end;
    extern uint32_t _stack;
    uint32_t count;
    uint32_t *ptr;
    uint32_t i;

    count = (((uint32_t)&_stack - (uint32_t)&_sbss_end) >> 2) - 2;
    ptr = (uint32_t *)((uint32_t)&_sbss_end & (~3));

    os_printf("ShowStack:%p:%p\r\n", &_sbss_end, &_stack);
    for (i = 0; i < count; i++)
        os_printf("0x%x:%p\r\n", &ptr[i], ptr[i]);
}

#if (DEBUG_AGC_MODE_CHANNEL_ASSESSMENT == 1)
extern void _LSLCacc_Read_AGC_Param(void);
#endif
extern void hfp_app_ptr_debug_printf(void);

#define HF_SCO_CONN 0
#define HF_SCO_DISCONN 1

#if A2DP_ROLE_SOURCE_CODE
extern void app_bt_sdp_connect(void);
#endif

extern void app_led_dump(void);

#if A2DP_ROLE_SOURCE_CODE
extern void set_sdp_browse_on(void);
extern result_t sdp_send_serviceSearchRequest(void);
extern void app_bt_sdp_send_serviceAttributeRequest(void);
#endif

extern uint32_t XVR_reg_0x24_save;
extern uint8_t edr_tx_edr_delay, edr_rx_edr_delay;

uint32_t M510_reg_process(uint8_t *buffer, uint32_t length)
{
    HCI_COMMAND_PACKET *hci_cmd = (HCI_COMMAND_PACKET *)buffer;

#if PTS_TESTING
    if ((hci_cmd->code == TRA_HCIT_COMMAND) && (hci_cmd->opcode.ogf == PTS_TESTING_OGF) && (hci_cmd->opcode.ocf == Mobvoi_OCF) && (length == (HCI_COMMAND_HEAD_LENGTH + hci_cmd->total)))
    {
        /*******************************************
         * uart cmd: 0x01 e0 40 01 10
         *                         10~4F for hfp
         *                         50~8F for a2dp
         *******************************************/
        pts_entry(hci_cmd->cmd);
        goto ret;
    }
#endif

    if ((hci_cmd->code != TRA_HCIT_COMMAND) || (hci_cmd->opcode.ogf != VENDOR_SPECIFIC_DEBUG_OGF) || (hci_cmd->opcode.ocf != Mobvoi_OCF) || (length != (HCI_COMMAND_HEAD_LENGTH + hci_cmd->total)))
        goto ret;

    switch (hci_cmd->cmd)
    {
    case Mobvoi_UART_LINK_CHECK:
        pHCItxBuf->total = length;
        memcpy(pHCItxBuf->param, uart_rx_buf, pHCItxBuf->total);
        break;

    case Mobvoi_UART_REGISTER_WRITE_CMD:
    {
        REGISTER_PARAM *tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH];
        REGISTER_PARAM *rx_param = (REGISTER_PARAM *)hci_cmd->param;

        pHCItxBuf->total = length - 1;
        memcpy(pHCItxBuf->param, uart_rx_buf, HCI_EVENT_HEAD_LENGTH);
        pHCItxBuf->param[3] = hci_cmd->cmd;
        tx_param->addr = rx_param->addr;
        tx_param->value = rx_param->value;
#if (CONFIG_BLUETOOTH_EN == 1)
        int reg_index;
        *(volatile unsigned int *)rx_param->addr = rx_param->value;
        reg_index = (rx_param->addr - MDU_XVR_BASE_ADDR) / 4;
        if ((reg_index >= 0) && (reg_index <= 0x0f))
            XVR_analog_reg_save[reg_index] = rx_param->value;
        if (reg_index == 0x24)
            XVR_reg_0x24_save = rx_param->value;
        if (reg_index == 0x27)
        {
            edr_tx_edr_delay = (rx_param->value >> 12) & 0x0f;
            // edr_rx_edr_delay = 1;
            edr_rx_edr_delay = (rx_param->value >> 8) & 0x0f;
            ;
        }
#endif
    }
    break;

    case Mobvoi_UART_REGISTER_READ_CMD:
    {
        int reg_index;

        REGISTER_PARAM *rx_param = (REGISTER_PARAM *)hci_cmd->param;
        REGISTER_PARAM *tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH];

        pHCItxBuf->total = HCI_EVENT_HEAD_LENGTH + length;
        memcpy(pHCItxBuf->param, uart_rx_buf, HCI_EVENT_HEAD_LENGTH);
        pHCItxBuf->param[3] = hci_cmd->cmd;
        tx_param->addr = rx_param->addr;

        reg_index = (rx_param->addr - MDU_XVR_BASE_ADDR) / 4;
#if (CONFIG_BLUETOOTH_EN == 1)
        if ((reg_index >= 0) && (reg_index <= 0x0f))
            tx_param->value = XVR_analog_reg_save[reg_index];
        else
            tx_param->value = *(volatile unsigned int *)rx_param->addr;
#else
        if ((reg_index >= 0) && (reg_index <= 0x0f))
            tx_param->value = 0x0;
        else
            tx_param->value = *(volatile unsigned int *)rx_param->addr;
#endif
    }
    break;

    case Mobvoi_FLASH_READ_CMD:
    {
        FLASH_PARAM *rx_param = (FLASH_PARAM *)hci_cmd->param;
        FLASH_PARAM *tx_param = (FLASH_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH];
        pHCItxBuf->total = HCI_COMMAND_HEAD_LENGTH + sizeof(FLASH_PARAM) + rx_param->len;
        memcpy(pHCItxBuf->param, uart_rx_buf, HCI_EVENT_HEAD_LENGTH);
        pHCItxBuf->param[3] = hci_cmd->cmd;
        memcpy((unsigned char *)tx_param, (unsigned char *)rx_param, sizeof(FLASH_PARAM));
        flash_read_data(tx_param->data, tx_param->addr, tx_param->len);
    }
    break;

    case Mobvoi_FLASH_WRITE_CMD:
    {
        FLASH_PARAM *rx_param = (FLASH_PARAM *)hci_cmd->param;
        FLASH_PARAM *tx_param = (FLASH_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH];
        pHCItxBuf->total = HCI_COMMAND_HEAD_LENGTH + sizeof(FLASH_PARAM);
        memcpy(pHCItxBuf->param, uart_rx_buf, HCI_EVENT_HEAD_LENGTH);
        pHCItxBuf->param[3] = hci_cmd->cmd;
        memcpy((unsigned char *)tx_param, (unsigned char *)rx_param, sizeof(FLASH_PARAM));
        flash_write_data(rx_param->data, rx_param->addr, rx_param->len);
    }
    break;

    case Mobvoi_FLASH_ERASE_CMD:
    {
        FLASH_PARAM *rx_param = (FLASH_PARAM *)hci_cmd->param;
        FLASH_PARAM *tx_param = (FLASH_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH];
        pHCItxBuf->total = HCI_COMMAND_HEAD_LENGTH + sizeof(tx_param->addr);
        memcpy(pHCItxBuf->param, uart_rx_buf, HCI_EVENT_HEAD_LENGTH);
        pHCItxBuf->param[3] = hci_cmd->cmd;
        memcpy((unsigned char *)tx_param, (unsigned char *)rx_param, sizeof(FLASH_PARAM));
        flash_erase_sector(rx_param->addr, FLASH_ERASE_4K);
    }
    break;

    case Mobvoi_SHOW_STACK_CMD:
        app_debug_showstack();
        goto ret;

    case Mobvoi_DUMP_ENV_CMD:
        app_env_dump();
        goto ret;

    case Mobvoi_CLEAR_LINKKEY_CMD:
        flash_erase_sector(FLASH_ENVDATA_DEF_ADDR, FLASH_ERASE_4K);
        break;

    case Mobvoi_SHOW_BT_STATUS:
#if (CONFIG_BLUETOOTH_EN == 1)
        app_bt_status_show();
#ifdef CONFIG_BLUETOOTH_AVDTP_SCMS_T
        security_control_cp_support_print();
#endif
#endif
        goto ret;

#ifdef Mobvoi_DEBUG

    case Mobvoi_SHOW_BT_DEBUG:
#if (CONFIG_BLUETOOTH_EN == 1)
        app_bt_debug_show();
#endif
        goto ret;
    case Mobvoi_LED_EQ_BUTTON:
        if (pHCIrxBuf->param[0] == 0xff)
            app_led_dump();
#ifdef CONFIG_APP_EQUANLIZER
#if (CONFIG_PRE_EQ == 1 || CONFIG_HFP_SPK_EQ == 1 || CONIFG_HFP_MIC_EQ == 1)
        else if (pHCIrxBuf->param[0] == 0xfe)
        {
            if (pHCIrxBuf->total >= 7)
            {
                if (pHCIrxBuf->param[5] == 0x00) // AUD
                {
                    sw_eq_flag = 1;
#if (CONFIG_PRE_EQ == 1)
                    app_set_eq_gain_enable(&(pHCIrxBuf->param[1]));
#endif
                }
                else if (pHCIrxBuf->param[5] == 0x01) // SPK
                {
                    sw_eq_flag = 2;
#if (CONFIG_HFP_SPK_EQ == 1)
                    app_set_spk_eq_gain_enable(&(pHCIrxBuf->param[1]));
#endif
                }
                else if (pHCIrxBuf->param[5] == 0x02) // MIC
                {
                    sw_eq_flag = 3;
#if (CONIFG_HFP_MIC_EQ == 1)
                    app_set_mic_eq_gain_enable(&(pHCIrxBuf->param[1]));
#endif
                }
                else
                    sw_eq_flag = 0;
            }
        }
        else if (pHCIrxBuf->param[0] == 0xfa)
        {
            if (sw_eq_flag == 1)
            {
#if (CONFIG_PRE_EQ == 1)
                app_set_pre_eq(&pHCIrxBuf->param[1]);
#endif
            }
            else if (sw_eq_flag == 2)
            {
#if (CONFIG_HFP_SPK_EQ == 1)
                app_set_hfp_spk_eq(&pHCIrxBuf->param[1]);
#endif
            }
            else if (sw_eq_flag == 3)
            {
#if (CONIFG_HFP_MIC_EQ == 1)
                app_set_hfp_mic_eq(&pHCIrxBuf->param[1]);
#endif
            }
        }
        else if (pHCIrxBuf->param[0] == 0xfb)
        {
#if (CONFIG_PRE_EQ == 1)
            app_show_pre_eq();
#endif
#if (CONFIG_HFP_SPK_EQ == 1)
            app_show_hfp_spk_eq();
#endif
#if (CONIFG_HFP_MIC_EQ == 1)
            app_show_hfp_mic_eq();
#endif
        }
        else if (pHCIrxBuf->param[0] == 0xfc)
        {
            if (sw_eq_flag == 1)
            {
#if (CONFIG_PRE_EQ == 1)
                app_set_pre_eq_gain(&pHCIrxBuf->param[1]);
#endif
            }
            else if (sw_eq_flag == 2)
            {
#if (CONFIG_HFP_SPK_EQ == 1)
                app_set_hfp_spk_eq_gain(&pHCIrxBuf->param[1]);
#endif
            }
            else if (sw_eq_flag == 3)
            {
#if (CONIFG_HFP_MIC_EQ == 1)
                app_set_hfp_mic_eq_gain(&pHCIrxBuf->param[1]);
#endif
            }
        }
        else if (pHCIrxBuf->param[0] == 0xfd)
            app_bt_flag2_set(APP_FLAG2_SW_MUTE, pHCIrxBuf->param[1]);
#endif
#endif
        else
            app_button_sw_action(pHCIrxBuf->param[0]);
        goto ret;

#if (CONFIG_BLUETOOTH_EN == 1)
#ifdef CONFIG_APP_AEC
    case Mobvoi_SET_AEC_PARA:
        app_aec_set_params(&hci_cmd->param[0]);
        goto ret;
#endif

#endif
#endif
    case Mobvoi_PRINT_LINK_KEY:
#if (CONFIG_BLUETOOTH_EN == 1)
        app_print_linkkey();
#endif
        goto ret;

    case Mobvoi_ENTRY_DUT_MODE:
#if (CONFIG_BLUETOOTH_EN == 1)
#if (CONFIG_CTRL_BQB_TEST_SUPPORT == 1)
        // 01E0FC05AF00000000
        // app_bt_enable_dut_mode(hci_cmd->param[0]);
        bt_app_entity_set_event(0, SYS_BT_DUT_MODE_EVENT);

#endif
#endif
        goto ret;
    case Mobvoi_ENTRY_FCC_TESTMODE:
        // 01 E0 FC 03 FC XX YY
#if (CONFIG_BLUETOOTH_EN == 1)
        app_bt_enable_fcc_mode(hci_cmd->param[0], hci_cmd->param[1]);
#endif
        goto ret;
    case Mobvoi_CMD_LPBG_CALI:
    {
        LPBG_calibration();
        goto ret;
    }
    case Mobvoi_CMD_WRITE_CALI:
    {
        write_cali_result();
        goto ret;
    }
    case Mobvoi_ENTRY_NON_SIG_TESTMODE:
    {
#if (CONFIG_BLUETOOTH_EN == 1)
        t_TestControl tc_contents;
        LSLCstat_Reset_Monitors();
        memcpy((uint8 *)&tc_contents, (uint8 *)&pHCIrxBuf->param[0], sizeof(t_TestControl));
        app_bt_enable_non_signal_test(&tc_contents);
        pHCItxBuf->total = uart_rx_index;
        memcpy(pHCItxBuf->param, uart_rx_buf, pHCItxBuf->total);
#endif
        break;
    }
#if (CONFIG_BLUETOOTH_EN == 1)
#if (DEBUG_BASEBAND_MONITORS == 1)
    case Mobvoi_READ_BASEBAND_MONITORS:
    {
        if (app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE))
            TC_Read_Non_Signal_Test_Monitors();
        else
            TC_Read_Local_Baseband_Monitors_Via_App();
        goto ret;
    }
    case Mobvoi_RESET_BASEBAND_MONITORS:
    {
        LSLCstat_Reset_Monitors();
        goto ret;
    }
#endif

#if (DEBUG_SCATTERNET_MONITORS == 1)
    case Mobvoi_READ_SCATTERNET_MONITORS:
        TC_Read_Local_LMPconfig_Monitors_Via_App();
        goto ret;
#endif

#if (DEBUG_AGC_MODE_CHANNEL_ASSESSMENT == 1)
    case Mobvoi_AGC_MODE_PARAM:
        _LSLCacc_Read_AGC_Param();
        goto ret;
#endif

    case Mobvoi_TEMP1_CMD:
        a2dp_cmd_disconnect();
        goto ret;
    case Mobvoi_TEMP2_CMD:
        hf_cmd_disconnect();
        goto ret;
    case Mobvoi_TEMP3_CMD:
        spp_slc_disconnect();
        goto ret;
#ifdef CONFIG_PRODUCT_TEST_INF
    case Mobvoi_RSSI_CMD:
        os_printf("rssi:0x%d,freqoffset:0x%x\r\n", aver_rssi, aver_offset);
        goto ret;
    case Mobvoi_TEST_SPP_AUDIOCONN:
        spp_send("AT+SPPPTT=1\r\n", 13);
        goto ret;
    case Mobvoi_TEST_SPP_AUDIODISCON:
        spp_send("AT+SPPPTT=0\r\n", 13);
        goto ret;
#else
    case Mobvoi_RSSI_CMD:
        goto ret;
#endif

    case Mobvoi_SHOW_SYSTEM_INFO:
        os_printf("Mobvoi_SHOW_SYSTEM_INFO.\r\n");
        show_bt_stack_status();
        goto ret;

#if A2DP_ROLE_SOURCE_CODE
    case Mobvoi_CMD_SDP_CONNECT:
        set_sdp_browse_on();
        app_bt_sdp_connect();
        goto ret;

    case Mobvoi_CMD_SERVICE_SEARCH_REQUEST:
        sdp_send_serviceSearchRequest();
        goto ret;

    case Mobvoi_CMD_SERVICE_ATTRIBUTE_REQUEST:
        app_bt_sdp_send_serviceAttributeRequest();
        goto ret;

    case Mobvoi_CMD_A2DP_SSA_REQUEST:
    {
        /* for a2dp sdp_query request. */
        extern result_t send_a2dp_ssa_request(void);
        send_a2dp_ssa_request();
    }
        goto ret;

    case Mobvoi_CMD_HFP_SSA_REQUEST:
    {
        /* for hfp sdp_query request. */
        extern result_t send_hfp_ssa_request(void);
        send_hfp_ssa_request();
    }
        goto ret;
#endif
#endif

#if CHARGER_VERIFY
    case Mobvoi_CMD_CHARGE_VERIFY_V4P25:
    {
        uint8_t result = 0;
        charger_vlcf_vcv_set(0); // vusb = 5v, vbat= 4.25v
        result = charger_vlcf_vcv_result(0);
        if (result < 16)
        {
            charger_vlcf_vcv_set(1);
            result = charger_vlcf_vcv_result(1);
            if (result > 16)
                os_printf("charger calibration check is ok\r\n");
        }
        if (result <= 16)
            os_printf("charger calibration check is NOT ok\r\n");
        goto ret;
    }
    case Mobvoi_CMD_CHARGE_VERIFY_V4P15:
    {
        uint8_t result = 0;
        charger_vlcf_vcv_set(0); // vusb = 5v, vbat= 4.15v
        result = charger_vlcf_vcv_result(0);
        if (result < 16)
        {
            charger_vlcf_vcv_set(1);
            result = charger_vlcf_vcv_result(1);
            if (result < 16)
                os_printf("charger calibration check is ok\r\n");
        }
        if (result >= 16)
            os_printf("charger calibration check is NOT ok\r\n");
        goto ret;
    }
    case Mobvoi_CMD_CHARGE_CALIBRATION:
        calib_dbg_enable(1);
        charger_vlcf_calibration(0);
        charger_vcv_calibration(0);
        calib_dbg_enable(0);
        goto ret;

    case Mobvoi_CMD_CHARGE_WRITE_RERSULT:
        goto ret;
#endif

    case Mobvoi_CMD_SYS_RESET:
        /* watchdog reset for uart download */
        if (hci_cmd->total >= 5)
        {
            uint32_t param = hci_cmd->param[0] << 24 | hci_cmd->param[1] << 16 | hci_cmd->param[2] << 8 | hci_cmd->param[3];
            if (param == 0x95279527)
            {
                /* watchdog reset */
                REG_WDT_0x00 = 0x5A0001;
                REG_WDT_0x00 = 0xA50001;
            }
        }
        goto ret;

    case Mobvoi_TRANSPARENT_HCI_CMD:
        if ((hci_cmd->total > 4) && (hci_cmd->total - hci_cmd->param[3] == 0x05))
        {
            uart_send_poll((uint8_t *)hci_cmd->param, hci_cmd->total - 1);
        }
        goto ret;

#if A2DP_ROLE_SOURCE_CODE
    case Mobvoi_CMD_A2DP_SRC_CONN_REMOTE_DEVICE:
    {
        /* for a2dpSrc connect remote device. */
        os_printf("Mobvoi_CMD_A2DP_SRC_CONN_REMOTE_DEVICE, %d\r\n", hci_cmd->total);

        btaddr_t remote_btaddr_def2 = {{0x86, 0x19, 0x36, 0x33, 0x22, 0x11}};

        if (hci_cmd->total >= 7)
        {
            uint8_t *input = hci_cmd->param;
            os_printf("A2DP_SRC_CONN_REMOTE:%02x:%02x:%02x:%02x:%02x:%02x\r\n", input[5], input[4], input[3], input[2], input[1], input[0]);
            memcpy((uint8_t *)&remote_btaddr_def2, (uint8_t *)input, sizeof(btaddr_t));
        }

        if (get_a2dp_role() == A2DP_ROLE_AS_SRC)
            a2dpSrcConnectRemoteDevice(&remote_btaddr_def2);
        else if (get_a2dp_role() == A2DP_ROLE_AS_SNK)
            a2dpSnkConnectRemoteDevice(&remote_btaddr_def2);
    }
        goto ret;
#endif

    case Mobvoi_SDIO_TEST: // 01 E0 FC 01 C2
        sd_test_write();
        goto ret;

#if CONFIG_USE_USB
    case Mobvoi_USB_DEVICE_TEST: // 01 E0 FC 02 C3 02 DEVICE
        // 01 E0 FC 02 C3 01 HOST
        //   usb_init(hci_cmd->param[0]);
        //     extern void  usb_join(void);
        //    usb_join();

        goto ret;
#endif

    case Mobvoi_CMD_APPEND_TLV:
    {
        uint16 type = (uint16)(pHCIrxBuf->param[2] << 8) | pHCIrxBuf->param[1];
        uint16 len = (uint16)(pHCIrxBuf->param[4] << 8) | pHCIrxBuf->param[3];
        app_append_tlv_data(pHCIrxBuf->param[0], type, &pHCIrxBuf->param[5], len);
        goto ret;
    }
#if (CONFIG_ANC_ENABLE == 1)
    case Mobvoi_ANC_DBG_CMD:
    {
        void app_anc_debug(HCI_COMMAND_PACKET *, HCI_EVENT_PACKET *);
        app_anc_debug((HCI_COMMAND_PACKET *)buffer, pHCItxBuf);
    }
    break;
#endif
    default:
        goto ret;
    }

    return 1;
ret:
    return 0;
}

void M510_Uart_Rx(void)
{
    if ((uart_rx_done != TRUE) || (uart_rx_index == 0))
        return;

    if (M510_reg_process((uint8_t *)uart_rx_buf, (uint32_t)uart_rx_index))
    	M510_Uart_Tx();

    clear_uart_buffer();
}

void M510_BTSPP_Rx(uint8_t *buffer, uint32_t length)
{
    if (M510_reg_process(buffer, length))
    {
        result_t spp_send(char *buff, uint32_t len);
        uint32_t tx_len = HCI_EVENT_HEAD_LENGTH + pHCItxBuf->total;
        pHCItxBuf->code = TRA_HCIT_EVENT;
        pHCItxBuf->event = HCI_COMMAND_COMPLETE_EVENT;
        spp_send((char *)uart_tx_buf, tx_len);
    }
}

void dbg_hci_rx_char(uint8_t ch)
{
    switch (s_dbg_hci_rx_state)
    {
    case DBG_HCI_STATE_RX_DATA_CONTINUE:
    __DBG_HCI_STATE_RX_DATA_CONTINUE:
        *s_dbg_hci_rx_pdu_buf = ch;
        s_dbg_hci_rx_pdu_buf++;
        s_dbg_hci_rx_pdu_length--;
        if (!s_dbg_hci_rx_pdu_length)
        {
            s_dbg_hci_rx_state = DBG_HCI_STATE_RX_DATA_COMMIT;
            goto __DBG_HCI_STATE_RX_DATA_COMMIT;
        }
        return;

    case DBG_HCI_STATE_RX_TYPE:
        if (ch == 0x01) // HCI_COMMAND
        {
            s_dbg_hci_rx_head_buf[0] = ch;
            s_dbg_hci_rx_state = DBG_HCI_STATE_RX_COMMAND_OPCODE1;
        }
        else
        {
            s_dbg_hci_rx_state = DBG_HCI_STATE_RX_TYPE;
            uart_rx_index = 0;
            uart_rx_done = FALSE;
        }
        return;

    case DBG_HCI_STATE_RX_COMMAND_OPCODE1:
        s_dbg_hci_rx_head_buf[1] = ch;
        s_dbg_hci_rx_state = DBG_HCI_STATE_RX_COMMAND_OPCODE2;
        return;

    case DBG_HCI_STATE_RX_COMMAND_OPCODE2:
        s_dbg_hci_rx_head_buf[2] = ch;
        s_dbg_hci_rx_state = DBG_HCI_STATE_RX_COMMAND_LENGTH;
        return;

    case DBG_HCI_STATE_RX_COMMAND_LENGTH:
        s_dbg_hci_rx_head_buf[3] = ch;
        s_dbg_hci_rx_pdu_length = ch;
        s_dbg_hci_rx_length = 4 + ch;
        s_dbg_hci_rx_state = DBG_HCI_STATE_RX_DATA_START;

        if (s_dbg_hci_rx_pdu_length == 0)
        {
            goto __DBG_HCI_STATE_RX_DATA_START;
        }
        return;

    case DBG_HCI_STATE_RX_DATA_START:
    __DBG_HCI_STATE_RX_DATA_START:
        s_dbg_hci_rx_pdu_buf = (volatile uint8_t *)&uart_rx_buf[4];
        if ((s_dbg_hci_rx_pdu_length == 0) || (s_dbg_hci_rx_pdu_length > 250))
        {
            s_dbg_hci_rx_state = DBG_HCI_STATE_RX_DATA_COMMIT;
            goto __DBG_HCI_STATE_RX_DATA_COMMIT;
        }
        s_dbg_hci_rx_state = DBG_HCI_STATE_RX_DATA_CONTINUE;
        goto __DBG_HCI_STATE_RX_DATA_CONTINUE;

    case DBG_HCI_STATE_RX_DATA_COMMIT:
    __DBG_HCI_STATE_RX_DATA_COMMIT:
        uart_rx_done = TRUE;
        uart_rx_index = s_dbg_hci_rx_length;
#if 0
            {
                uint8_t i;
                os_printf("===hci_dbg:\r\n");
                for(i=0;i<s_dbg_hci_rx_length;i++)
                {
                    os_printf("%02x,",uart_rx_buf[i]);
                }
                os_printf("===\r\n");
            }
#endif
            M510_Uart_Rx();
        s_dbg_hci_rx_state = DBG_HCI_STATE_RX_TYPE;
        return;
    default:
        return;
    }
    return;
}
uint8_t g_keyvalue;
void uart_handler(void)
{
    uint32_t status;
    uint8_t value;
    status = REG_UART0_INT_STATUS;
    if (status & (MSK_UART0_INT_STATUS_RX_FIFO_NEED_READ | MSK_UART0_INT_STATUS_RX_STOP_END))
    {
        while (REG_UART0_FIFO_STATUS & MSK_UART0_FIFO_STATUS_FIFO_RD_READY)
        {
            value = (REG_UART0_FIFO_PORT & MSK_UART0_FIFO_PORT_RX_FIFO_DOUT) >> 8;
            if (BT_HOST_MODE == NONE_CONTROLLER)
                juart_receive(&value, 1);
            else if ((BT_HOST_MODE == JUNGO_HOST))
            {
#if 0
                uart_rx_buf[uart_rx_index++] = value;
                if (uart_rx_index == RX_FIFO_THRD)
                    uart_rx_index = 0;
                uart_rx_done = TRUE;;
#endif
#if (CONFIG_USE_USB == 0)
                dbg_hci_rx_char(value);
#endif
                if (value == 'd' || value == 'e')
                    g_keyvalue = value;
            }
            else
                TRAhcit_Rx_Char(value);
        }
    }
    REG_UART0_INT_STATUS = status;
}
void uart1_handler(void)
{
	os_printf("Func = %s ,Line = %d \n",__func__,__LINE__);
    uint32_t status;
    uint8_t value;
    status = REG_UART1_INT_STATUS;
    if (status & (MSK_UART1_INT_STATUS_RX_FIFO_NEED_READ | MSK_UART1_INT_STATUS_RX_STOP_END))
    {
        while (REG_UART1_FIFO_STATUS & MSK_UART1_FIFO_STATUS_FIFO_RD_READY)
        {
            value = (REG_UART1_FIFO_PORT & MSK_UART1_FIFO_PORT_RX_FIFO_DOUT) >> 8;
			
			os_printf("value %c\r\n",value);
            if (BT_HOST_MODE == NONE_CONTROLLER)
                juart_receive(&value, 1);
            else if ((BT_HOST_MODE == JUNGO_HOST))
            {
#if 0
                uart_rx_buf[uart_rx_index++] = value;
                if (uart_rx_index == RX_FIFO_THRD)
                    uart_rx_index = 0;
                uart_rx_done = TRUE;;
#endif
#if (CONFIG_USE_USB == 1)
                if (value == 'd' || value == 'e')
                    g_keyvalue = value;
                dbg_hci_rx_char(value);
#endif
            }
            else
                TRAhcit_Rx_Char(value);
        }
    }
    REG_UART1_INT_STATUS = status;
}

void show_bt_stack_status(void)
{
    os_printf("%s\r\n", __func__);

    os_printf("sizeof(struct m_hdr):%d, sizeof(struct mbuf):%d\r\n", sizeof(struct m_hdr), sizeof(struct mbuf));

    os_printf("Mobvoi SW Compliled at %s, %s\r\n", __TIME__, __DATE__);
}

#ifdef Mobvoi_DEBUG
#ifdef A2DP_SBC_DUMP_SHOW
extern void a2dp_sbc_info_show(void);
extern void sbc_encode_frame_info(void);
#endif
#if (CONFIG_BLUETOOTH_EN == 1)

void app_bt_debug_show(void)
{
    extern int encode_pkts;
    extern int decode_pkts;
    extern int encode_buffer_full;
    extern int encode_buffer_empty;

#ifdef A2DP_SBC_DUMP_SHOW
    a2dp_sbc_info_show();
    sbc_encode_frame_info();
#endif

    os_printf("--------sbc decode statistic--------------\r\n");

    os_printf("| encode pkts: %d\r\n", encode_pkts);
    os_printf("| decode pkts: %d\r\n", decode_pkts);
    os_printf("| encode full: %d\r\n", encode_buffer_full);
    os_printf("|encode empty: %d\r\n", encode_buffer_empty);
    os_printf("| encode node: %d\r\n", sbc_buf_get_node_count());
    os_printf("--------sbc decode statistic--------------\r\n");

    os_printf("memory status: \r\n");
    memory_usage_show();
    os_printf("--------tick status----------------------\r\n");
    os_printf("|           sleep tick: %d\r\n", sleep_tick);
    os_printf("|       powerdown tick: %d\r\n", pwdown_tick);
    os_printf("| sniffmode_wakeup_dly: %d\r\n", sniffmode_wakeup_dly);
    os_printf("--------tick status----------------------\r\n");

    return;
}

void app_bt_debug_info_clear(void)
{
    extern int encode_pkts;
    extern int decode_pkts;
    extern int encode_buffer_full;
    extern int encode_buffer_empty;

    encode_pkts = 0;
    decode_pkts = 0;
    encode_buffer_full = 0;
    encode_buffer_empty = 0;
}
#endif

void app_bt_status_show(void)
{
    app_handle_t app_h = app_get_sys_handler();

    os_printf("Mobvoi SW Compliled at %s, %s\r\n", __TIME__, __DATE__);
    print_page_scan_status();
    /* bt_app_management */
    bt_app_entity_print_state();

    {
        uint32_t flag;
        uint8_t i;
        os_printf("------------------------------------------\r\n");
        for (i = 0; i < BT_MAX_AG_COUNT; i++)
        {
            flag = get_hf_priv_flag(i, 0xffffffff);
            os_printf("|    hfp-private flag %d:%08x\r\n", i, flag);
            flag = get_a2dp_priv_flag(i, 0xffffffff);
            os_printf("|   a2dp-private flag %d:%08x\r\n", i, flag);
        }
        os_printf("------------------------------------------\r\n");
    }

    if (app_h->unit == NULL)
    {
        os_printf("Bluetooth device not initialized yet.\r\n");
        return;
    }
    os_printf("     HFP flag:%08x\r\n", get_hf_priv_flag(0, 0xffffffff));
    os_printf("    a2dp flag:%08x\r\n", get_a2dp_priv_flag(0, 0xffffffff));
    os_printf("Global Flag-1:%08x\r\n", app_h->flag_sm1);
    os_printf("Global Flag-2:%08x\r\n", app_h->flag_sm2);
#if (CONFIG_AUD_FADE_IN_OUT == 1)
    extern void aud_fade_status_debug(void);
    aud_fade_status_debug();
#endif
    extern uint8_t syspwr_cpu_halt;
    extern int SYSpwr_Is_Available_Sleep_System(void);
    extern BOOL USLCsleep_Is_Tabasco_Asleep(void);
    os_printf("Sleep is allowed:%d,%d,%d,%d\r\n", app_is_available_sleep_system(), syspwr_cpu_halt, SYSpwr_Is_Available_Sleep_System(), USLCsleep_Is_Tabasco_Asleep());
    os_printf("CPU irq mask:%08x\r\n", get_spr(SPR_VICMR(0)));

    os_printf("Device addr: " BTADDR_FORMAT "\r\n", BTADDR(&(app_h->unit->hci_btaddr)));
    if (app_h->flag_sm1 & APP_FLAG_ACL_CONNECTION)
        os_printf("Remote device addr: " BTADDR_FORMAT "\r\n", BTADDR(&(app_h->remote_btaddr)));
    else
    {
        os_printf("Not connect to other device. 0x%x \r\n", app_h->flag_sm1);
        return;
    }

    os_printf("A2DP status: %s\r\n",
              (app_h->flag_sm1 & APP_FLAG_A2DP_CONNECTION) ? "connected" : "disconnected");

    if (app_h->flag_sm1 & APP_FLAG_MUSIC_PLAY)
        os_printf("Audio stream started now.\r\n");

    os_printf("AVRCP status: %s\r\n",
              (app_h->flag_sm1 & APP_FLAG_AVCRP_CONNECTION) ? "connected" : "disconnected");

    os_printf("HFP status: %s\r\n",
              (app_h->flag_sm1 & APP_FLAG_HFP_CONNECTION) ? "connected" : "disconnected");
}

#endif
